import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class PCADemo {
    public static void main(String[] args) {
        // 加载数据集
        IrisDataset iris = new IrisDataset();
        double[][] features = iris.getFeatures();
        String[] labels = iris.getLabels();

        System.out.println("原始数据维度: " + features[0].length);
        System.out.println("样本数量: " + features.length);

        // 创建PCA实例并拟合数据
        PCA pca = new PCA();
        pca.fit(features);

        // 计算方差解释率
        double[] explainedVariance = pca.getExplainedVarianceRatio();
        System.out.println("\n各主成分的方差解释率:");
        for (int i = 0; i < explainedVariance.length; i++) {
            System.out.printf("主成分 %d: %.4f (%.2f%%)%n",
                    i + 1, explainedVariance[i], explainedVariance[i] * 100);
        }

        // 计算累计方差解释率
        System.out.println("\n累计方差解释率:");
        double cumulative = 0;
        for (int i = 0; i < explainedVariance.length; i++) {
            cumulative += explainedVariance[i];
            System.out.printf("前 %d 个主成分: %.4f (%.2f%%)%n",
                    i + 1, cumulative, cumulative * 100);
        }

        // 降维到2维
        int nComponents = 2;
        double[][] transformed = pca.transform(features, nComponents);

        System.out.println("\n降维后的数据 (前10个样本):");
        System.out.println("PC1\t\tPC2\t\t类别");
        for (int i = 0; i < Math.min(10, transformed.length); i++) {
            System.out.printf("%.4f\t%.4f\t%s%n",
                    transformed[i][0], transformed[i][1], labels[i]);
        }

        // 显示数据统计信息
        displayStatistics(transformed, labels);
    }

    private static void displayStatistics(double[][] data, String[] labels) {
        System.out.println("\n=== 降维后数据统计 ===");

        // 按类别分组统计
        String[] uniqueLabels = Arrays.stream(labels).distinct().toArray(String[]::new);

        for (String label : uniqueLabels) {
            List<double[]> classData = new ArrayList<>();
            for (int i = 0; i < data.length; i++) {
                if (labels[i].equals(label)) {
                    classData.add(data[i]);
                }
            }

            double[] meanPC1 = new double[2];
            double[] stdPC1 = new double[2];

            for (int j = 0; j < 2; j++) {
                double sum = 0;
                for (double[] sample : classData) {
                    sum += sample[j];
                }
                meanPC1[j] = sum / classData.size();

                double variance = 0;
                for (double[] sample : classData) {
                    variance += Math.pow(sample[j] - meanPC1[j], 2);
                }
                stdPC1[j] = Math.sqrt(variance / classData.size());
            }

            System.out.printf("\n类别: %s%n", label);
            System.out.printf("主成分1 - 均值: %.4f, 标准差: %.4f%n", meanPC1[0], stdPC1[0]);
            System.out.printf("主成分2 - 均值: %.4f, 标准差: %.4f%n", meanPC1[1], stdPC1[1]);
        }
    }
}